Skip to content

explicit tail calls: support indirect arguments#151143

Merged
rust-bors[bot] merged 2 commits intorust-lang:mainfrom
folkertdev:tail-call-indirect
Feb 28, 2026
Merged

explicit tail calls: support indirect arguments#151143
rust-bors[bot] merged 2 commits intorust-lang:mainfrom
folkertdev:tail-call-indirect

Conversation

@folkertdev
Copy link
Copy Markdown
Contributor

@folkertdev folkertdev commented Jan 14, 2026

View all comments

tracking issue: #112788

After discussion in #144855, I was wrong and it is actually possible to support tail calls with PassMode::Indirect { on_stack: false, .. } arguments.

Normally an indirect argument with on_stack: false would be passed as a pointer into the caller's stack frame. For tail calls, that would be unsound, because the caller's stack frame is overwritten by the callee's stack frame.

Therefore we store the argument for the callee in the corresponding caller's slot. Because guaranteed tail calls demand that the caller's signature matches the callee's, the corresponding slot has the correct type.

To handle cases like the one below, the tail call arguments must first be copied to a temporary, and can only then be copied to the caller's argument slots.

// A struct big enough that it is not passed via registers.
pub struct Big([u64; 4]);

fn swapper(a: Big, b: Big) -> (Big, Big) {
    become swapper_helper(b, a);
}

I'm not really familiar with MIR and what tricks/helpers we have, so I'm just cobbling this together. Hopefully we can arrive at something more elegant.

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

F-explicit_tail_calls `#![feature(explicit_tail_calls)]` S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants